package m

import (
	"fmt"
	//"strconv"
	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Common/data"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	//"GameServer/ServerGameutils"
)

// 关卡信息
type LockBlocks struct {
	BaseM
	Uid             bson.ObjectId              `bson:"_id" json:"_id"`
	robot           bool                       // 是否是 机器人创建的
	LockBlocks      map[int64]*LockBlockSimple `bson:"lockBlocks" json:"lockBlocks,omitempty"` // 关卡信息
	RobotLockBlocks map[int64]*LockBlock       `bson:"-" json:"robotLockBlocks,omitempty"`     // 机器人关卡信息
}

// 关卡简单数据
type LockBlockSimple struct {
	Mid  string `bson:"mid" json:"mid"` // 唯一id
	Tid  int64  `bson:"tid" json:"tid"`
	Star int64  `bson:"star" json:"star"` // 已经获得星星数量
}

// 关卡
type LockBlock struct {
	BaseM
	Mid         string                    `bson:"_id" json:"_id"` // 唯一id
	Uid         string                    `bson:"uid" json:"uid"` // 玩家uid
	Tid         int64                     `bson:"tid" json:"tid"`
	Robot       bool                      `bson:"-" json:"robot"` // 是否是 机器人创建的
	Layers      map[int64]string          `bson:"layers" json:"layers,omitempty"`
	RobotLayers map[int64]*Layer          `bson:"-" json:"robotLayers"` // 机器人层信息
	GridNum     int64                     `bson:"gridNum" json:"gridNum"`
	GridOpenNum int64                     `bson:"gridOpenNum" json:"gridOpenNum"`
	Star        int64                     `bson:"star" json:"star"`       // 已经获得星星数量
	StarNum     int64                     `bson:"starNum" json:"starNum"` // 星星总数量
	Status      int64                     `bson:"status" json:"status"`
	Num         int64                     `bson:"num" json:"num"` // 通关次数
	Monsters    map[int64]map[int64]int64 `bson:"monsters" json:"monsters,omitempty"`
	Story       *Story                    `bson:"story" json:"story,omitempty"` // 故事绘本

	TvNum          int64 `bson:"tvNum" json:"tvNum"`                   // 电视机总数量
	BombNum        int64 `bson:"bombNum" json:"bombNum"`               // 炸弹总数量
	CrystalballNum int64 `bson:"crystalballNum" json:"crystalballNum"` // 水晶球总数量

	MagicBookRedNum    int64 `bson:"magicBookRedNum" json:"magicBookRedNum"`       // 魔法书-红 总数量
	MagicBookBlueNum   int64 `bson:"magicBookBlueNum" json:"magicBookBlueNum"`     // 魔法书-蓝 总数量
	MagicBookPurpleNum int64 `bson:"magicBookPurpleNum" json:"magicBookPurpleNum"` // 魔法书-紫 总数量

	DriftingBottleNum int64 `bson:"driftingBottleNum" json:"driftingBottleNum"` // 漂流瓶 总数量
	// ChristmasBallNum     int64 `bson:"christmasBallNum" json:"christmasBallNum"`         // 圣诞装饰球 总数量
	// ChristmasCandyNum    int64 `bson:"christmasCandyNum" json:"christmasCandyNum"`       // 圣诞拐棍糖 总数量
	// ChristmasStockingNum int64 `bson:"christmasStockingNum" json:"christmasStockingNum"` // 圣诞圣诞袜 总数量
}

// 故事
type Story struct {
	Tid     int64 `bson:"tid" json:"tid"`         // 绘本配置id
	LayerId int64 `bson:"layerId" json:"layerId"` // 层id
	Status  int64 `bson:"status" json:"status"`   // 状态 0 正常  1 已经打开  2 已经领取奖励
}

// 层
type Layer struct {
	BaseM
	Mid            string              `bson:"_id" json:"_id"` // 唯一id
	Uid            string              `bson:"uid" json:"uid"` // 玩家uid
	Robot          bool                `bson:"-" json:"robot"` // 是否是 机器人创建的
	Tid            int64               `bson:"tid" json:"tid"`
	Id             int64               `bson:"id" json:"id"`
	GridList       map[int64]*GridInfo `bson:"gridList" json:"gridList,omitempty"`
	Status         int64               `bson:"status" json:"status"`
	Altars         []*Altar            `bson:"altars" json:"altars"` // 祭坛
	InGridId       int64               `bson:"inGridId" json:"inGridId"`
	StarNum        int64               `bson:"starNum" json:"starNum"`
	StoryGridIds   []int64             `bson:"storyGridIds" json:"storyGridIds"` // 故事绘本所在的格子信息
	IsFirstIn      int64               `bson:"isFirstIn" json:"isFirstIn"`       // 0 没有进入  1 已经进入
	TvNum          int64               `bson:"tvNum" json:"tvNum"`
	BombNum        int64               `bson:"bombNum" json:"bombNum"`
	CrystalballNum int64               `bson:"crystalballNum" json:"crystalballNum"`

	MagicBookRedNum    int64 `bson:"magicBookRedNum" json:"magicBookRedNum"`
	MagicBookBlueNum   int64 `bson:"magicBookBlueNum" json:"magicBookBlueNum"`
	MagicBookPurpleNum int64 `bson:"magicBookPurpleNum" json:"magicBookPurpleNum"`

	DriftingBottleNum int64 `bson:"driftingBottleNum" json:"driftingBottleNum"`

	// ChristmasBallNum     int64 `bson:"christmasBallNum" json:"christmasBallNum"`
	// ChristmasCandyNum    int64 `bson:"christmasCandyNum" json:"christmasCandyNum"`
	// ChristmasStockingNum int64 `bson:"christmasStockingNum" json:"christmasStockingNum"`
}

// 格子信息
type GridInfo struct {
	Id       int64  `bson:"id" json:"id"`             // 格子id 0开始
	Tid      int64  `bson:"tid" json:"tid"`           // 砖块tid
	Status   int64  `bson:"status" json:"status"`     // 需要打开的次数 2：需要打开2次，1：需要打开1次
	Goods    *Goods `bson:"goods" json:"goods"`       // 格子中的道具
	ExtId    int64  `bson:"extId" json:"extId"`       // 记录旧砖块Tid
	StatusEx int64  `bson:"statusEx" json:"statusEx"` // 1 格子上锁

	Head        string `bson:"head" json:"head"`               // 放火玩家的头像
	AvatarFrame int64  `bson:"avatarFrame" json:"avatarFrame"` // 放火玩家的头像框
}

//祭坛
type Altar struct {
	Status  int64   `bson:"status" json:"status"` //祭坛是否被打开 0 没有被打开  1 已经被打开 2 已经领取奖励
	Typ     int     `bson:"typ" json:"typ"`
	GridIds []int64 `bson:"gridIds" json:"gridIds"` //祭坛所在的格子id列表
}

func NewLockBlocks() cache.EntryI {
	return &LockBlocks{LockBlocks: make(map[int64]*LockBlockSimple, 0)}
}

// 设置为机器人创建的关卡
func (lockBlocks *LockBlocks) SetRobot(flag bool) {
	lockBlocks.robot = flag
}

// 保存信息
func (lockBlocks *LockBlocks) Save() (err error) {

	if lockBlocks.robot {
		return
	}
	err = dbmodule.MgoDB.GameDB.Upsert("lockBlocks", bson.M{"_id": lockBlocks.Uid}, &lockBlocks)
	if err != nil {
		fmt.Println("lockBlocks err:", err)
		return
	}
	return
}

func (lockBlocks *LockBlocks) Load(key interface{}) (err error) {
	if lockBlocks.robot {
		return errors.New("机器人")
	}
	switch key.(type) {
	case string:
		lockBlocks.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		lockBlocks.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "LockBlocks_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return lockBlocks.LoadData()
}

// 加载数据
func (lockBlocks *LockBlocks) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("lockBlocks", bson.M{"_id": lockBlocks.Uid}, nil, &lockBlocks)
	if err != nil {
		if err.Error() == "not found" {
			//err = errors.NewErrcode(data.Errcode.UserNotFound, fmt.Sprintf("没有找到关卡列表信息. uid:%s", lockBlocks.Uid.Hex()))
			return nil
		}
		return
	}
	return
}

// 更新数据
func (lockBlocks *LockBlocks) Update(val *LockBlocks) {
	Cache.Put("lockBlocks", lockBlocks.Uid.Hex(), val)
	val.UpdateData()
}

// 更新数据
func (lockBlocks *LockBlocks) UpdateLockBlockSimple(val *LockBlockSimple) {
	if val.Mid == "" {
		panic("关卡mid 为空")
	}
	if v, ok := lockBlocks.LockBlocks[val.Tid]; ok {
		if v.Star != val.Star {
			lockBlocks.LockBlocks[val.Tid] = val
			lockBlocks.Update(lockBlocks)
		}
		return
	}

	lockBlocks.LockBlocks[val.Tid] = val
	lockBlocks.Update(lockBlocks)
}

// 更新数据
func (lockBlocks *LockBlocks) UpdateLockBlock(val *LockBlock) {
	if val.Mid == "" {
		panic("关卡mid 为空")
	}
	lockBlocks.UpdateLockBlockSimple(&LockBlockSimple{Mid: val.Mid, Tid: val.Tid, Star: val.Star})
}

// 增加关卡
func (lockBlocks *LockBlocks) AddLockBlock(req *LockBlock) {
	if req.Mid == "" {
		panic("关卡mid 为空")
	}
	lockBlocks.UpdateLockBlockSimple(&LockBlockSimple{Mid: req.Mid, Tid: req.Tid, Star: req.Star})
	req.Update(req)
	return
}

//
func NewLockBlock() cache.EntryI {
	return &LockBlock{Layers: make(map[int64]string, 0), Monsters: make(map[int64]map[int64]int64, 0), Story: new(Story)}
}

// 关卡
// 保存信息
func (lockBlock *LockBlock) Save() (err error) {
	if lockBlock.Robot {
		return
	}
	err = dbmodule.MgoDB.GameDB.Upsert("lockBlock", bson.M{"_id": lockBlock.Mid}, lockBlock)
	if err != nil {
		return
	}
	return
}

func (lockBlock *LockBlock) Load(key interface{}) (err error) {
	lockBlock.Mid = key.(string)
	return lockBlock.LoadData()
}

// 加载数据
func (lockBlock *LockBlock) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("lockBlock", bson.M{"_id": lockBlock.Mid}, nil, &lockBlock)
	if err != nil {
		if err.Error() == "not found" {
			return err
		}
		return
	}
	return
}

// 更新数据
func (lockBlock *LockBlock) Update(val *LockBlock) {
	if val.Mid == "" {
		panic("关卡mid 为空")
	}
	Cache.Put("lockBlock", val.Mid, val)
	val.UpdateData()
}

func NewLayer() cache.EntryI {
	return &Layer{GridList: make(map[int64]*GridInfo, 0)}
}

// 保存信息
func (layer *Layer) Save() (err error) {
	if layer.Robot {
		return errors.New("机器人")
	}
	err = dbmodule.MgoDB.GameDB.Upsert("layer", bson.M{"_id": layer.Mid}, &layer)
	if err != nil {
		fmt.Println("lockBlock err:", err)
		return
	}
	return
}

func (layer *Layer) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		layer.Mid = key.(string)
	case bson.ObjectId:
		layer.Mid = key.(bson.ObjectId).Hex()
	default:
		log.WithFields(log.Fields{
			"method": "layer_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return layer.LoadData()
}

// 加载数据
func (layer *Layer) LoadData() (err error) {
	if layer.Robot {
		return errors.New("机器人")
	}
	err = dbmodule.MgoDB.GameDB.FindOne("layer", bson.M{"_id": layer.Mid}, nil, &layer)
	if err != nil {
		if err.Error() == "not found" {
			err = errors.NewErrcode(data.Errcode.UserNotFound, fmt.Sprintf("没有找到层信息 uid:%s  mid: %s", layer.Uid, layer.Mid))
			return
		}
		return
	}
	return
}

// 更新数据
func (layer *Layer) Update(val *Layer) {
	Cache.Put("layer", val.Mid, val)
	val.UpdateData()
}

// 更新格子信息
func (layer *Layer) UpdateGrid(val *GridInfo) {
	layer.GridList[val.Id] = val
	layer.Update(layer)
}

// 更新格子信息
func (layer *Layer) UpdateGridByMap(mlsit map[int64]*GridInfo) {
	for _, item := range mlsit {
		layer.GridList[item.Id] = item
	}
	layer.Update(layer)
}

// 关卡添加层
func (l *LockBlock) AddLayer(layer *Layer) {
	if _, ok := l.Layers[layer.Id]; ok {
		return
	}
	l.Layers[layer.Id] = layer.Mid
	layer.Update(layer)
	l.Update(l)
}

// 关卡获取层
func (l *LockBlock) GetLayer(id int64) (r *Layer, ok bool) {
	if layerMid, ok := l.Layers[id]; ok {
		v, ok := Cache.Get("layer", layerMid)
		if !ok {
			log.WithFields(log.Fields{
				"method": "LockBlock_GetLayer",
				"data":   id,
			}).Error("not found")
			return nil, false
		}
		r = v.(*Layer)
		return r, true
	}
	return
}

func (l *LockBlock) GetLayerByMid(mid string) (r *Layer, ok bool) {
	v, ok := Cache.Get("layer", mid)
	if !ok {
		log.WithFields(log.Fields{
			"method": "LockBlockGetLayerByMid",
			"data":   mid,
		}).Error("not found")
		return nil, false
	}
	r = v.(*Layer)
	return r, true

}

func (l *Layer) GetGrid(id int64) (r *GridInfo) {
	r = l.GridList[id]
	return
}

// 获取关卡信息
func (u *User) GetLockBlock(id int64) (r *LockBlock, ok bool) {
	lockBlocks := u.LockBlocks()
	if lockBlocks.robot {
		r, ok = lockBlocks.RobotLockBlocks[id]
		return
	}

	lockBlocksKey, ok := lockBlocks.LockBlocks[id]
	if !ok {
		return
	}
	v, ok := Cache.Get("lockBlock", lockBlocksKey.Mid)
	if !ok {
		return
	}
	r = v.(*LockBlock)
	return
}

// 获取当前所在的格子信息
func (u *User) GetGrid(id int64) (g *GridInfo, ok bool) {
	lockBlock, ok := u.GetLockBlock(u.Pos.LockBlockTid)
	if !ok {
		return
	}

	if u.Robot { // 机器人
		layer := lockBlock.RobotLayers[u.Pos.LayerId]
		g = layer.GetGrid(id)
		return
	}
	layer := u.GetLayer()
	if layer == nil {
		return nil, false
	}
	g = layer.GetGrid(id)
	return
}

// 玩家当前层
func (u *User) GetLayer() (layer *Layer) {
	lockBlock, ok := u.GetLockBlock(u.Pos.LockBlockTid)
	if !ok {
		log.WithFields(log.Fields{
			"uid":    u.Uid.Hex(),
			"method": "GetLayer",
			"data":   u,
		}).Error("没有获取到关卡信息")
	}
	if u.Robot {
		layer = lockBlock.RobotLayers[u.Pos.LayerId]
		return
	}

	layerMid, ok := lockBlock.Layers[u.Pos.LayerId]
	if !ok {
		log.WithFields(log.Fields{
			"uid":    u.Uid.Hex(),
			"method": "GetLayer",
			"data":   u,
		}).Error("没有获取到层信息")
	}

	v, _ := Cache.Get("layer", layerMid)
	layer = v.(*Layer)
	return
}

// 获取当前关卡
func (u *User) GetCurrentLockBlock() (r *LockBlock) {
	r, ok := u.GetLockBlock(u.Pos.LockBlockTid)
	if !ok {
		panic(fmt.Sprintf("获取当前关卡失败：%d", u.Pos.LockBlockTid))
	}
	return
}

// 获取上一层
func (u *User) PreLayer() (layer *Layer, err error) {
	if u.Pos.LayerId == 1 {
		err = errors.NewErrcode(data.Errcode.NoPreLayer, "已经是第一层")
		return
	}
	defer u.Update(u)
	u.Pos.LayerId--
	layer = u.GetLayer()
	u.ResetCurrentLayerOpenGridNum()
	return
}

func (u *User) NextLayer() (layer *Layer, ok bool) {
	nextTid := u.Pos.LayerId + 1
	lockBlock, ok := u.GetLockBlock(u.Pos.LockBlockTid)
	if !ok {
		return
	}
	defer u.Update(u)
	if layerMid, ok := lockBlock.Layers[nextTid]; ok {
		u.Pos.LayerId++
		if u.Pos.LockBlockTid >= u.MaxPos.LockBlockTid {
			if u.Pos.LayerId > u.MaxPos.LayerId {
				u.MaxPos.LayerId = u.Pos.LayerId
			}
		}
		u.ResetCurrentLayerOpenGridNum()
		v, _ := Cache.Get("layer", layerMid)
		layer = v.(*Layer)
		return layer, true
	}
	return nil, false
}

func (u *User) AddLayer(layer *Layer) {
	lockBlock := u.GetCurrentLockBlock()
	lockBlock.AddLayer(layer)
}

// 前一关
func (u *User) PreLockBlock() (r *LockBlock, err error) {
	if u.Pos.LockBlockTid == 1 {
		err = errors.NewErrcode(data.Errcode.NoPreLevelDoor, "已经是第一关")
		return
	}
	defer u.Update(u)
	u.Pos.LockBlockTid--
	r = u.GetCurrentLockBlock()
	u.Pos.LayerId = 1
	u.ResetCurrentLayerOpenGridNum()
	return
}

// 设置当前关卡
func (u *User) SetCurrentLockBlock(req *LockBlock) {
	defer u.Update(u)
	l := u.LockBlocks()
	// 如果是新的就添加
	l.AddLockBlock(req)
	u.Pos.LockBlockTid = req.Tid
	u.Pos.LayerId = 1
	u.ResetCurrentLayerOpenGridNum()
}

// 下一关
// func (u *User) NextLockBlock() (r *LockBlock, ok bool) {
// 	nextTid := u.Pos.LockBlockTid + 1
// 	if v, ok := u.GetLockBlock(nextTid); ok {
// 		defer u.Update(u)
// 		u.Pos.LockBlockTid = nextTid
// 		u.Pos.LayerId = 1
// 		if u.Pos.LockBlockTid >= u.MaxPos.LockBlockTid {
// 			// 设置最大关卡
// 			u.MaxPos.LockBlockTid = u.Pos.LockBlockTid
// 			u.MaxPos.LayerId = 1
// 		}
// 		u.ResetCurrentLayerOpenGridNum()
// 		return v, true
// 	}
// 	return
// }

func (u *User) LockBlocks() (r *LockBlocks) {
	v, _ := Cache.Get("lockBlocks", u.Uid.Hex())
	r = v.(*LockBlocks)
	return
}

// 新增层
func (u *User) AddLockBlock(req *LockBlock) {
	l := u.LockBlocks()
	l.AddLockBlock(req)
}

// 关卡移动
func (u *User) MoveLockBlock(id int64) {
	defer u.Update(u)
	u.Pos.LockBlockTid = id
	u.Pos.LayerId = 1
}

// 层级移动
func (u *User) MoveLayer(id int64) {
	defer u.Update(u)
	u.Pos.LayerId = id
}

// 重置 当前层打开的格子数
func (u *User) ResetCurrentLayerOpenGridNum() {
	defer u.Update(u)
	layer := u.GetLayer()
	u.Pos.LayerOpenGridNum = 0
	for _, item := range layer.GridList {
		if item.Status == 0 {
			u.Pos.LayerOpenGridNum++
		}
	}
}
